package com.google.gwt.sample.dynatablerf.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.sample.dynatablerf.client.events.CloseMaterialListEvent;
import com.google.gwt.sample.dynatablerf.client.events.CloseMaterialListEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.CloseProjetoEvent;
import com.google.gwt.sample.dynatablerf.client.events.CloseProjetoEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.CloseProjetoListEvent;
import com.google.gwt.sample.dynatablerf.client.events.CloseProjetoListEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.CloseServicoListEvent;
import com.google.gwt.sample.dynatablerf.client.events.CloseServicoListEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.GoToMaterialListEvent;
import com.google.gwt.sample.dynatablerf.client.events.GoToMaterialListEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.GoToProjetoEvent;
import com.google.gwt.sample.dynatablerf.client.events.GoToProjetoEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.GoToProjetoListEvent;
import com.google.gwt.sample.dynatablerf.client.events.GoToProjetoListEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.GoToProjetoStartViewEvent;
import com.google.gwt.sample.dynatablerf.client.events.GoToProjetoStartViewEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.GoToServicoListEvent;
import com.google.gwt.sample.dynatablerf.client.events.GoToServicoListEventHandler;
import com.google.gwt.sample.dynatablerf.client.events.GoToStartViewEvent;
import com.google.gwt.sample.dynatablerf.client.events.GoToStartViewEventHandler;
import com.google.gwt.sample.dynatablerf.client.presenters.MainPresenter;
import com.google.gwt.sample.dynatablerf.client.presenters.MaterialProjetoListPresenter;
import com.google.gwt.sample.dynatablerf.client.presenters.MultipleSelectionDataPresenter.MultipleSelectionDataDisplay;
import com.google.gwt.sample.dynatablerf.client.presenters.ProjetoListPresenter;
import com.google.gwt.sample.dynatablerf.client.presenters.ProjetoPresenter;
import com.google.gwt.sample.dynatablerf.client.presenters.ProjetoPresenter.ProjetoDisplay;
import com.google.gwt.sample.dynatablerf.client.presenters.ProjetoStartPresenter;
import com.google.gwt.sample.dynatablerf.client.presenters.ProjetoStartPresenter.ProjetoStartDisplay;
import com.google.gwt.sample.dynatablerf.client.presenters.ServicoProjetoListPresenter;
import com.google.gwt.sample.dynatablerf.client.presenters.SingleSelectionDataPresenter.SingleSelectionDataDisplay;
import com.google.gwt.sample.dynatablerf.client.presenters.StartPresenter;
import com.google.gwt.sample.dynatablerf.client.views.MainView;
import com.google.gwt.sample.dynatablerf.client.views.MaterialProjetoListView;
import com.google.gwt.sample.dynatablerf.client.views.ProjetoListView;
import com.google.gwt.sample.dynatablerf.client.views.ProjetoStartView;
import com.google.gwt.sample.dynatablerf.client.views.ProjetoView;
import com.google.gwt.sample.dynatablerf.client.views.ServicoProjetoListView;
import com.google.gwt.sample.dynatablerf.client.views.StartView;
import com.google.gwt.sample.dynatablerf.shared.GrifoRequestFactory;
import com.google.gwt.sample.dynatablerf.shared.GrifoRequestTransport;
import com.google.gwt.sample.dynatablerf.shared.GrifoTransportInterceptor;
import com.google.gwt.sample.dynatablerf.shared.IGrifoTransportInterceptor;
import com.google.gwt.sample.dynatablerf.shared.MaterialProjetoProxy;
import com.google.gwt.sample.dynatablerf.shared.ProjetoProxy;
import com.google.gwt.sample.dynatablerf.shared.ServicoProjetoProxy;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TabLayoutPanel;

public class GrifoAppController {

	private EventBus eventBus;
	private Panel rootPanel;
	private GrifoRequestFactory requestFactory;

	private Map<ProjetoProxy, ProjetoDisplay> projetoDisplayMap;
	private SingleSelectionDataDisplay<ProjetoProxy> projetoListDisplay;
	private Map<ProjetoProxy, MultipleSelectionDataDisplay<MaterialProjetoProxy>> materialListDisplayMap;
	private Map<ProjetoProxy, MultipleSelectionDataDisplay<ServicoProjetoProxy>> servicoListDisplayMap;
	private List<ProjetoProxy> projetoStartDisplayList;

	public GrifoAppController(Panel rootPanel) {
		super();
		this.rootPanel = rootPanel;
		this.eventBus = new SimpleEventBus();
		this.projetoDisplayMap = new HashMap<ProjetoProxy, ProjetoPresenter.ProjetoDisplay>();
		this.materialListDisplayMap = new HashMap<ProjetoProxy, MultipleSelectionDataDisplay<MaterialProjetoProxy>>();
		this.servicoListDisplayMap = new HashMap<ProjetoProxy, MultipleSelectionDataDisplay<ServicoProjetoProxy>>();
		this.projetoStartDisplayList = new ArrayList<ProjetoProxy>();
		createGrifoRequestFactory();
	}

	public void start() {
		bind();
		openMainPresenter();
	}

	private void bind() {

		eventBus.addHandler(CloseMaterialListEvent.TYPE,
				new CloseMaterialListEventHandler() {

					@Override
					public void onCloseMaterialList(CloseMaterialListEvent event) {
						closeMaterialListView(event.getProjetoProxy());

					}
				});

		eventBus.addHandler(GoToMaterialListEvent.TYPE,
				new GoToMaterialListEventHandler() {

					@Override
					public void onGoToMaterialList(GoToMaterialListEvent event) {
						openMaterialListView(event.getContainer(),
								event.getProjetoProxy(), event.getEventBus());

					}
				});
		eventBus.addHandler(CloseServicoListEvent.TYPE,
				new CloseServicoListEventHandler() {

					@Override
					public void onCloseServicoList(CloseServicoListEvent event) {
						closeServicoListView(event.getProjetoProxy());

					}
				});

		eventBus.addHandler(GoToServicoListEvent.TYPE,
				new GoToServicoListEventHandler() {

					@Override
					public void onGoToServicoList(GoToServicoListEvent event) {
						openServicoListView(event.getContainer(),
								event.getProjetoProxy(), event.getEventBus());

					}
				});

		eventBus.addHandler(GoToProjetoStartViewEvent.TYPE,
				new GoToProjetoStartViewEventHandler() {

					@Override
					public void onGoToProjetoStartView(
							GoToProjetoStartViewEvent event) {
						openProjetoStartView(event.getContainer(),
								event.getProjetoProxy(), event.getEventBus());

					}
				});

		eventBus.addHandler(CloseProjetoListEvent.TYPE,
				new CloseProjetoListEventHandler() {

					@Override
					public void onCloseProjetoList(CloseProjetoListEvent event) {
						closeProjetoListView();

					}
				});

		eventBus.addHandler(CloseProjetoEvent.TYPE,
				new CloseProjetoEventHandler() {

					@Override
					public void onCloseProjeto(CloseProjetoEvent event) {
						closeProjetoView(event.getProjetoProxy());

					}
				});

		eventBus.addHandler(GoToStartViewEvent.TYPE,
				new GoToStartViewEventHandler() {

					@Override
					public void onGoToStartView(GoToStartViewEvent event) {
						openStartView(event.getContainer());

					}
				});

		eventBus.addHandler(GoToProjetoEvent.TYPE,
				new GoToProjetoEventHandler() {

					@Override
					public void onGoToProjeto(final GoToProjetoEvent event) {
						openProjetoView(event.getProjetoProxy(),
								event.getContainer());

					}
				});

		eventBus.addHandler(GoToProjetoListEvent.TYPE,
				new GoToProjetoListEventHandler() {

					@Override
					public void onGoToProjetoList(GoToProjetoListEvent event) {
						openProjetoListView(event.getContainer());
					}
				});
	}

	private void openProjetoView(final ProjetoProxy projetoProxy,
			final TabLayoutPanel container) {
		ProjetoDisplay projetoView = getProjetoDisplay(projetoProxy);
		ProjetoPresenter presenter = new ProjetoPresenter(projetoView,
				projetoProxy, eventBus, requestFactory);
		presenter.go(container);
	}

	private void closeProjetoView(ProjetoProxy projetoProxy) {
		projetoDisplayMap.remove(projetoProxy);
		materialListDisplayMap.remove(projetoProxy);
		servicoListDisplayMap.remove(projetoProxy);
		projetoStartDisplayList.remove(projetoProxy);
	}

	private ProjetoDisplay getProjetoDisplay(ProjetoProxy projetoProxy) {
		ProjetoDisplay projetoDisplay = null;
		if (projetoDisplayMap.containsKey(projetoProxy))
			projetoDisplay = projetoDisplayMap.get(projetoProxy);
		else {
			projetoDisplay = new ProjetoView();
			projetoDisplayMap.put(projetoProxy, projetoDisplay);
		}
		return projetoDisplay;
	}

	private void createGrifoRequestFactory() {
		requestFactory = GWT.create(GrifoRequestFactory.class);
		IGrifoTransportInterceptor grifoTransportInterceptor = new GrifoTransportInterceptor();
		GrifoRequestTransport transport = new GrifoRequestTransport(
				grifoTransportInterceptor);
		requestFactory.initialize(eventBus, transport);
	}

	private void openProjetoListView(final TabLayoutPanel container) {

		projetoListDisplay = getProjetoListDisplay();
		ProjetoListPresenter projetoListPresenter = new ProjetoListPresenter(
				projetoListDisplay, requestFactory, eventBus);
		projetoListPresenter.go(container);
	}

	private void openMainPresenter() {
		MainView mainView = new MainView();
		MainPresenter mainPresenter = new MainPresenter(mainView, eventBus);
		mainPresenter.go(rootPanel);
	}

	private void openStartView(final TabLayoutPanel container) {
		StartView startView = new StartView();
		StartPresenter startPresenter = new StartPresenter(startView, eventBus);
		startPresenter.go(container);
	}

	private SingleSelectionDataDisplay<ProjetoProxy> getProjetoListDisplay() {
		if (projetoListDisplay == null)
			projetoListDisplay = new ProjetoListView();
		return projetoListDisplay;
	}

	private void closeProjetoListView() {
		projetoListDisplay = null;
	}

	private void openProjetoStartView(final TabLayoutPanel container,
			final ProjetoProxy projetoProxy, final EventBus eventBus) {
		if (!projetoStartDisplayList.contains(projetoProxy)) {
			projetoStartDisplayList.add(projetoProxy);
			ProjetoStartDisplay projetoStartView = new ProjetoStartView();
			ProjetoStartPresenter presenter = new ProjetoStartPresenter(
					eventBus, projetoStartView, projetoProxy);
			presenter.go(container);
		}
	}

	private void openMaterialListView(final TabLayoutPanel container,
			final ProjetoProxy projetoProxy, EventBus eventBus) {
		MaterialProjetoListPresenter presenter = new MaterialProjetoListPresenter(
				getMaterialListDisplay(projetoProxy), projetoProxy,
				requestFactory, eventBus);
		presenter.go(container);

	}

	private MultipleSelectionDataDisplay<MaterialProjetoProxy> getMaterialListDisplay(
			ProjetoProxy projetoProxy) {
		MultipleSelectionDataDisplay<MaterialProjetoProxy> materialListDisplay = null;
		if (materialListDisplayMap.containsKey(projetoProxy))
			materialListDisplay = materialListDisplayMap.get(projetoProxy);
		else {
			materialListDisplay = new MaterialProjetoListView();
			materialListDisplayMap.put(projetoProxy, materialListDisplay);
		}
		return materialListDisplay;
	}

	private void closeMaterialListView(ProjetoProxy projetoProxy) {
		materialListDisplayMap.remove(projetoProxy);
	}

	private void openServicoListView(final TabLayoutPanel container,
			final ProjetoProxy projetoProxy, EventBus eventBus) {
		ServicoProjetoListPresenter presenter = new ServicoProjetoListPresenter(
				getServicoListDisplay(projetoProxy), projetoProxy,
				requestFactory, eventBus);
		presenter.go(container);

	}

	private MultipleSelectionDataDisplay<ServicoProjetoProxy> getServicoListDisplay(
			ProjetoProxy projetoProxy) {
		MultipleSelectionDataDisplay<ServicoProjetoProxy> servicoListDisplay = null;
		if (servicoListDisplayMap.containsKey(projetoProxy))
			servicoListDisplay = servicoListDisplayMap.get(projetoProxy);
		else {
			servicoListDisplay = new ServicoProjetoListView();
			servicoListDisplayMap.put(projetoProxy, servicoListDisplay);
		}
		return servicoListDisplay;
	}

	private void closeServicoListView(ProjetoProxy projetoProxy) {
		servicoListDisplayMap.remove(projetoProxy);
	}
}
